// --------------------------------------------------------------------
    // 进程间通信的方式：管道、消息队列、共享内存、信号量、信号、socket
// --------------------------------------------------------------------

#include <unistd.h>
#include <string>
#include <cstring>
#include <errno.h>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

void AnonymousPipe(){
    // fd[0]代表读端，fd[1]代表写端
    int fd[2];
    int ret=pipe(fd);
    if(ret==-1){
        // strerror 将errno转换为相应的字符串，但需要手动输出
        std::cerr<<strerror(errno)<<std::endl;
        exit(1);
    }
    // fork创建子进程，若返回-1，则表示错误，errno被设置；若返回大于0表示父进程，等于0表示子进程
    pid_t pt=fork();
    if(pt==-1){
        std::cerr<<strerror(errno)<<std::endl;
        exit(2);
    }
    if(pt>0){
        close(fd[0]);
        std::cout<<"I am father"<<std::endl;
        sleep(5);
        std::string mes="hello ymbx";
        // write系统调用向fd中写入字符
        // 当返回-1时，提示错误，errno被设置；
        // 当返回0时，若fd指向普通文件则说明写入的大小为0，若fd指向非普通文件（socket、pipe等），则说明连接或管道已经关闭；
        // 其余返回写入的字节数
        if(write(fd[1],mes.c_str(),mes.size())!=mes.size()){
            // perror 为stderr输出的错误信息，会自动解析errno并将其转换为字符串
            perror("write to pipe");
            exit(3);
        }
    }else{
        close(fd[1]);
        std::cout<<"I am son"<<std::endl;
        char buffer[1024];
        // read系统调用从fd中读取字符
        // 当返回-1时，表示错误，errno被设置；
        // 其余情况下遇到eof停止，返回读取到的字节数
        if(read(fd[0],buffer,sizeof(buffer))==-1){
            perror("read from pipe");
            exit(4);
        }
        std::cout<<buffer<<std::endl;
    }
}
void NamedPipe(){
    // mkfifo 和 mkfifoat 的区别若传入的pathname是相对路径，前者是相对于当前位置的相对路径，后者则是相对于第一参数dir的相对路径
    // int ret2=mkfifoat(AT_FDCWD,"./namedp2",0664);
    // 文件的实际权限是  mode & （~umask）
    int ret =mkfifo("./namedp",0664);
    if(ret==-1){
        perror("create named pipe");
        exit(5);
    }
    int fd=open("./namedp",O_RDONLY);
    if(fd<0){
        perror("open named pipe error");
        exit(6);
    }
    while(1){
        char buf[1024];
        ssize_t n=read(fd,buf,sizeof(buf)-1);
        if(n>0){
            buf[n-1]=0;  // 正确设置字符串结束符
            printf("client send>>>%s\n",buf);
        }else if(n==0){
            continue;
        }else{
            perror("read error");
            exit(7);
        }
    }
    close(fd);
    unlink("./namedp");
}


int main(){
    // AnonymousPipe();
    NamedPipe();
    return 0;
}